package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"imooc.com/ccmouse/u2pppw/getProxy/redis"
)

var (
	ipRe = regexp.MustCompile(`([\d]+.[\d]+.[\d]+.[\d]+:[\d]+)<br>`)
	wg   sync.WaitGroup
)

const URL = "http://www.89ip.cn/tqdl.html?api=1&num=50&port=&address=&isp="

func main() {

	ticker := time.NewTicker(time.Minute * 1)
	go func() {
		for range ticker.C {
			go func() {
				testRedisProxy()
				getProxy()
			}()
		}
	}()

	go getProxy()

	r := gin.Default()

	r.GET("/proxy", func(c *gin.Context) {
		proxyArr := redis.GetAllProxy(0, -1)
		c.JSON(200, gin.H{
			"proxy": proxyArr,
			"count": len(proxyArr),
		})
	})

	r.GET("/", func(c *gin.Context) {
		c.Redirect(http.StatusTemporaryRedirect, "/proxy")
	})

	r.Run()

}

func getProxy() {
	log.Println("getProxy start")
	resp, err := http.Get(URL)
	if err != nil {
		log.Println(err)
		return
	}
	defer resp.Body.Close()

	bytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		return
	}

	submatch := ipRe.FindAllSubmatch(bytes, -1)

	proxyArr := redis.GetAllProxy(0, -1)

	//wg.Add(len(submatch))

	start := time.Now()
	for i, match := range submatch {
		flag := false
		s := string(match[1])
		//检查redis是否已存在 已存在则不处理
		for _, v := range proxyArr {
			v = strings.Trim(v, "[]")
			if v == s {
				flag = true
				log.Println(s, "exists, ignore")
				break
			}
		}
		if flag {
			continue
		}

		wg.Add(1)
		go func(index int, s string) {
			err := testProxy(s)
			if err == nil {
				log.Println(s, "success, add")
				_, err := redis.AddProxy(s)
				if err != nil {
					log.Println(s, err)
				}
			} else if err != nil {
				log.Println(s, "fail")
			}
			wg.Done()
		}(i, s)
	}
	wg.Wait()

	fmt.Println("耗时", time.Now().Sub(start))
	log.Println("getProxy end")
}

func testRedisProxy() {
	proxyArr := redis.GetAllProxy(0, -1)
	log.Println("testRedisProxy start", "共", len(proxyArr), "个")
	wg.Add(len(proxyArr))
	start := time.Now()
	for i, v := range proxyArr {
		v = strings.Trim(v, "[]")
		go func(index int, s string) {
			err := testProxy(s)
			if err != nil {
				redis.DeleteProxy(proxyArr[index])
				log.Println(s, "fail, delete")
			} else {
				log.Println(s, "success")
			}
			wg.Done()
		}(i, v)
	}
	wg.Wait()
	fmt.Println("耗时", time.Now().Sub(start))
	log.Println("testRedisProxy end")
}

func testProxy(url1 string) error {
	defer func() {
		if r := recover(); r != nil {
			log.Println(r)
		}
	}()
	proxy := func(_ *http.Request) (*url.URL, error) {
		return url.Parse("http://" + url1)
	}
	transport := &http.Transport{Proxy: proxy}
	client := &http.Client{
		Transport: transport,
		Timeout:   time.Second * 10,
	}
	resp, err := client.Get(URL) //请求并获取到对象,使用代理
	if err == nil {
		resp.Body.Close()
	}

	return err
}

func ReadConsole(callback func(string)) {

	for {

		// 从标准输入读取字符串，以\n为分割
		text, err := bufio.NewReader(os.Stdin).ReadString('\n')
		if err != nil {
			break
		}

		// 去掉读入内容的空白符
		text = strings.TrimSpace(text)

		callback(text)

	}

}
